package pku;

import snappy.Snappy;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class MessageReader {

    private int thcount = 0;

    private RandomAccessFile[] rafs;

    private byte[] rBytes = new byte[Constants.MSGAP + Constants.MSGlEN];
    private byte[] bytes = new byte[Constants.MSGAP + Constants.MSGlEN];

    private int count;
    private int limit;

    private RandomAccessFile raf;

    private boolean over = false;

    private DefaultMessage msg = new DefaultMessage();
    
    private DefaultKeyValue dkv = new DefaultKeyValue(16);

    public MessageReader(String dir) throws IOException {
        File dirFile = new File(dir);
        if (!dirFile.exists()) {
            this.over = true;
            return;
        }
        File[] files = dirFile.listFiles();
        if (files.length <= 0) {
            this.over = true;
            return;
        }
        rafs = new RandomAccessFile[files.length];
        for (int i = 0; i < files.length; i++) {
            rafs[i] = new RandomAccessFile(files[i], "r");
        }
        raf = rafs[thcount++];
    }

    public ByteMessage read() throws Exception {
        if (over) {
            return null;
        }
        if (count < limit) {
            return fromBuffer();
        }
        int len = 0;
        while ((len = raf.readShort()) == 0) {
            if (thcount == rafs.length) {
                this.over = true;
                return null;
            }
            raf = rafs[thcount++];

        }


        raf.read(rBytes, 0, len);

        limit = Snappy.uncompress(rBytes, 0, len, bytes, 0);
        count = 0;

        return fromBuffer();
    }


    private ByteMessage fromBuffer() {

        int keySize = getByte();
        dkv.clear();
        for (int i = 0; i < keySize; i++) {
            String key = MessageHeader.strs[getByte()];
            dkv.put(key, getBytes());
        }
        msg.setHeaders(dkv);
        msg.setBody(getBytes());
        return msg;
    }

    public byte getByte() {
        return (byte) (bytes[count++] & 0xff);
    }

    public String getString() {
        int a = getLen();
        String s = new String(bytes, count, a);
        count += a;
        return s;
    }

    public byte[] getBytes() {
        int a = getLen();
        byte[] b = new byte[a];
        System.arraycopy(bytes, count, b, 0, a);
        count += a;
        return b;
    }

    private int getLen() {

        return (bytes[count++] & 0xff)|((bytes[count++] & 0xff)<<8)|((bytes[count++] & 0xff)<<16)|((bytes[count++] & 0xff)<<24);

    }
}

